﻿Option Strict On
Option Explicit On

Imports System.Drawing

Public Class ClikinAPI

    Private Declare Function SetCursorPos& Lib "user32" (ByVal x As Int32, ByVal y As Int32)
    Private Declare Function mouse_event& Lib "user32" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal dy As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32)
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Int32) As UShort

    Private Const MOUSEEVENTF_ABSOLUTE = &H8000     ' absolute move
    Private Const MOUSEEVENTF_LEFTDOWN = &H2        ' left button down
    Private Const MOUSEEVENTF_LEFTUP = &H4          ' left button up
    Private Const MOUSEEVENTF_MOVE = &H1            ' mouse move
    Private Const MOUSEEVENTF_MIDDLEDOWN = &H20      ' middle button down
    Private Const MOUSEEVENTF_MIDDLEUP = &H40        ' middle button up
    Private Const MOUSEEVENTF_RIGHTDOWN = &H8        ' right button down
    Private Const MOUSEEVENTF_RIGHTUP = &H10         ' right button up

    Private Const ERR_INVALID_BUTTON As String = "Button ""{0}"" is not a valid value. Please use button values between 0 and 2."

    Public Const VK_ESCAPE = &H1B                   'Escape key
    Public Const VK_LBUTTON = &H1                  'Left mouse button
    Public Const VK_RBUTTON = &H2                  'Right mouse button
    Public Const VK_MBUTTON = &H4                  'Middle mouse button
    Public Const VK_STATE_UP = 0
    Public Const VK_STATE_UP_CHANGED = 1
    Public Const VK_STATE_DOWN = 32768
    Public Const VK_STATE_DOWN_CHANGED = 32769


    Public Shared Sub MoveMouse(ByVal x As Int32, ByVal y As Int32)
        SetCursorPos(x, y)
    End Sub

    Public Shared Sub Sleep(ByVal milliseconds As Int32)
        Threading.Thread.Sleep(New TimeSpan(0, 0, 0, 0, milliseconds))
    End Sub

    Public Shared Sub ClickMouse(Optional ByVal delay As Int32 = 50, Optional ByVal buttonNumber As Int32 = 0)
        Select Case buttonNumber
            Case 0
                mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                Sleep(delay)
                mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
            Case 1
                mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0)
                Sleep(delay)
                mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0)
            Case 2
                mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
                Sleep(delay)
                mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
            Case Else
                Throw New ArgumentException(String.Format(ERR_INVALID_BUTTON, buttonNumber))
        End Select
    End Sub

    Public Shared Sub ButtonMouse(ByVal buttonDown As Boolean, ByVal buttonNumber As Int32)

        Select Case buttonNumber
            Case 0
                If buttonDown Then
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                Else
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                End If
            Case 1
                If buttonDown Then
                    mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0)
                Else
                    mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0)
                End If
            Case 2
                If buttonDown Then
                    mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
                Else
                    mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
                End If
            Case Else
                Throw New ArgumentException(String.Format(ERR_INVALID_BUTTON, buttonNumber))
        End Select

    End Sub

    Public Shared Function WasKeyHit(ByVal virtualKey As Int32) As Boolean
        Dim output As Boolean = False
        Dim keyState As UShort
        keyState = GetAsyncKeyState(virtualKey)

        'check if last bit is set
        If ((keyState And &H1) = 1) Then
            output = True
        End If

        Return output
    End Function

    Public Shared Function WhatIsKeyState(ByVal virtualKey As Int32) As UShort
        Return GetAsyncKeyState(virtualKey)
    End Function

End Class
